#!/usr/bin/env python
#
#       Data_tab.py
#       
#       Copyright 2009 Brandon Invergo <brandon@brandoninvergo.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import sys
import locale

try:
    import pygtk
    #tell pyGTK, if possible, that we want GTKv2
    pygtk.require("2.0")
except:
    #Some distributions come with GTK2, but not pyGTK
    pass

try:
    import gtk
    import gtk.glade
    
except:
    print "You need to install pyGTK or GTKv2 ",
    print "or set your PYTHONPATH correctly."
    print "try: export PYTHONPATH=",
    print "/usr/local/lib/python2.2/site-packages/"
    sys.exit(1)

from gobject import TYPE_INT, TYPE_STRING

class Data_tab:
    data_objects = set()
    
    def on_data_objects_selected(self, widget):
        self.data_objects_edit_button.set_sensitive(True)
        self.data_objects_remove_button.set_sensitive(True)

    def on_data_objects_remove(self, widget):
        cursor = self.dt_treeview.get_cursor()[0]
        tree_iter = self.dt_treestore.get_iter(cursor)
        object_name = self.dt_treestore.get_value(tree_iter,0)
        if not self.r_eng.delete_object(object_name):
            self.show_error("Error deleting object")
        else:
            self.update_data_view()
    
    def match_datatree_val(self, model, path, iter, data):
        if model.get_value(iter, 0) == data[0]:
            data[1].append(path)
        return False         
    
    def append_data_treeview(self, new_objects, parent):
        for obj in new_objects:
            if type(obj) == type(str()):
                object_type = self.main_window.r_eng.get_type(obj)
                object_len = self.main_window.r_eng.get_length(obj)
                dt_iter = self.dt_treestore.append(parent, \
                    [obj, object_type, object_len])
                parent_path = self.dt_treestore.get_path(parent)
                parent_iter = self.dt_treestore.get_iter(parent_path)
                if parent_path == self.data_sets_ref.get_path():
                    count = self.dt_treestore.get(parent_iter, 2)[0] + 1
                    self.dt_treestore.set_value(parent_iter, 2, count)
                elif parent_path == self.other_objects_ref.get_path():
                    count = self.dt_treestore.get(parent_iter, 2)[0] + 1
                    self.dt_treestore.set_value(parent_iter, 2, count)    
            elif type(obj) == type(list()):
                self.append_data_treeview(obj, dt_iter)
        return
    
    def dt_namecol_func(self, column, cell, model, iter):
        if model.iter_parent(iter) == None:
            name = model.get_value(iter, 0)
            cell.set_property('markup', "<b>" + name + "</b>")
        return

    def update_data_view(self):
        """This function updates the data tab with new objects that have
        been added and removes objects that no longer exist. This needs to be improved to handle data sets which 
        have members"""
        data_objects_temp = self.main_window.r_eng.get_objects()
        new_objects = list(data_objects_temp - self.data_objects)
        new_objects_copy = list(new_objects)
        new_data_frames = list()
        data_frame_names = list()
        data_sets_path = self.data_sets_ref.get_path()
        data_sets_iter = self.dt_treestore.get_iter(data_sets_path)
        other_objects_path = self.other_objects_ref.get_path()
        other_objects_iter = self.dt_treestore.get_iter(other_objects_path)
        for obj in new_objects_copy:
            if self.main_window.r_eng.is_data_frame(obj):
                new_data_frames.append(obj)
                data_frame_names.append(obj)
                names = self.main_window.r_eng.get_dataframe_names(obj)
                new_data_frames.append(names)
                new_objects.remove(obj)
        if len(new_objects) > 0:
            self.append_data_treeview(new_objects, other_objects_iter)
            self.data_objects = self.data_objects | set(new_objects)
        if len(new_data_frames) > 0:
            self.append_data_treeview(new_data_frames, data_sets_iter)
            self.data_objects = self.data_objects | set(data_frame_names)
        
        old_objects = list(self.data_objects - data_objects_temp)
        if len(old_objects) > 0:
            for obj in old_objects:
                pathlist = []
                self.dt_treestore.foreach(self.match_datatree_val, \
                    (obj, pathlist))
                pathlist.reverse()
                for path in pathlist:
                    iter = self.dt_treestore.get_iter(path)
                    if self.dt_treestore.is_ancestor(other_objects_iter, iter):
                        count = self.dt_treestore.get(other_objects_iter, 2)[0] - 1
                        self.dt_treestore.set_value(other_objects_iter, 2, count)
                    else:
                        count = self.dt_treestore.get(data_sets_iter, 2)[0] - 1
                        self.dt_treestore.set_value(data_sets_iter, 2, count)
                    self.dt_treestore.remove(iter)
            self.data_objects = self.data_objects - set(old_objects)
        self.dt_treeview.show()
        
    def __init__(self, parent_window, glade_gui):
        self.main_window = parent_window
      
        self.dt_treestore = gtk.TreeStore(TYPE_STRING, TYPE_STRING, \
            TYPE_INT)
        
        dt_iter = self.dt_treestore.append(None, \
            ["Data sets","",0])
        data_sets_path = self.dt_treestore.get_path(dt_iter)
        self.data_sets_ref = gtk.TreeRowReference(self.dt_treestore, \
            data_sets_path)            
        
        dt_iter = self.dt_treestore.append(None, \
            ["Other objects","",0])
        other_objects_path = self.dt_treestore.get_path(dt_iter)
        self.other_objects_ref = gtk.TreeRowReference(self.dt_treestore, \
            other_objects_path)            
            
        self.dt_treeview = glade_gui.get_widget("Data_objects_tree")
        self.dt_treeview.set_model(self.dt_treestore)
        dt_namecol = gtk.TreeViewColumn("Name")
        self.dt_treeview.append_column(dt_namecol)
        dt_namecell = gtk.CellRendererText()
        dt_namecol.pack_start(dt_namecell, True)
        dt_namecol.set_cell_data_func(dt_namecell, self.dt_namecol_func)

        dt_typecol = gtk.TreeViewColumn("Type")
        self.dt_treeview.append_column(dt_typecol)
        dt_typecell = gtk.CellRendererText()
        dt_typecol.pack_start(dt_typecell, True)
                
        dt_ncol = gtk.TreeViewColumn("n")
        self.dt_treeview.append_column(dt_ncol)
        dt_ncell = gtk.CellRendererText()
        dt_ncol.pack_start(dt_ncell, True)
        dt_namecol.add_attribute(dt_namecell, 'text', 0)
        dt_typecol.add_attribute(dt_typecell, 'text', 1)
        dt_ncol.add_attribute(dt_ncell, 'text', 2)
        
        callbacks = {"on_Data_objects_tree_cursor_changed": self.on_data_objects_selected,\
            "on_Data_objects_remove" : self.on_data_objects_remove}
        glade_gui.signal_autoconnect(callbacks)
        
        self.data_objects_edit_button = glade_gui.get_widget("Data_objects_edit")
        self.data_objects_remove_button = glade_gui.get_widget("Data_objects_remove")
